package com.mustafaiev.tair.cts.tapestry.pages.baskets;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.InjectPage;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.corelib.components.Form;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.util.EnumValueEncoder;

import com.mustafaiev.tair.cts.enums.PurchaseType;
import com.mustafaiev.tair.cts.exeptions.DataNotStoredException;
import com.mustafaiev.tair.cts.facade.IBasketFacade;
import com.mustafaiev.tair.cts.facade.IPurchaseFacade;
import com.mustafaiev.tair.cts.factory.ICostTrackingSystemFacadeFactory;
import com.mustafaiev.tair.cts.tapestry.dto.BasketDTO;
import com.mustafaiev.tair.cts.tapestry.dto.PurchaseDTO;
import com.mustafaiev.tair.cts.tapestry.encoder.PurchaseEncoder;

public class Edit extends ManageBasket {

	private static final Logger LOGGER = Logger.getLogger(Edit.class);

	@Inject
	private ICostTrackingSystemFacadeFactory facadeFactory;

	@InjectPage
	private View viewPage;

	@Persist
	private String costs;

	@Property
	@Persist
	private BasketDTO basket;

	@Property
	@Persist
	private List<PurchaseDTO> purchases;

	@Persist
	private PurchaseDTO purchase;

	@Component(id = "editBasketForm")
	private Form form;

	@InjectComponent
	private Zone purchasesEditZone;

	@InjectComponent
	private Zone costsZone;

	@Inject
	private Request request;

	@Property
	@Persist
	private PurchaseEncoder encoder;

	@Property
	@Persist
	private EnumValueEncoder<PurchaseType> purchaseTypeEncoder;

	@Inject
	private TypeCoercer typeCoercer;

	private boolean formInSubmition;

	private ArrayList<PurchaseDTO> submittedPurchases;

	public PurchaseDTO getPurchase() {
		return this.purchase;
	}

	public void setPurchase(final PurchaseDTO purchase) {
		this.purchase = purchase;
		purchase.setBasket(this.basket);
		if (this.formInSubmition) {
			this.submittedPurchases.add(purchase);
		}
	}

	public String getCosts() {
		return this.costs;
	}

	public boolean isDisabled() {
		return PurchaseType.COMMON.equals(this.purchase.getType());
	}

	public void init(final BasketDTO basket, final List<PurchaseDTO> purchases) {
		this.basket = basket;
		this.purchases = purchases;
	}

	@SetupRender
	public void prepareValues() {
		this.encoder = new PurchaseEncoder(getPurchaseFacade());
		this.purchaseTypeEncoder = new EnumValueEncoder<PurchaseType>(
				this.typeCoercer, PurchaseType.class);
		this.costs = getPurchasesCosts();
	}

	void onActivate() {
		this.formInSubmition = false;
	}

	public Object onCostsChanged() {
		this.costs = this.request.getParameter("param");
		return this.request.isXHR() ? this.costsZone.getBody() : null;
	}

	public void onPrepareForSubmit() {
		this.formInSubmition = true;
		this.submittedPurchases = new ArrayList<PurchaseDTO>();
	}

	public void onValidateFromEditBasketForm() {
		try {
			this.basket.setPurchases(this.submittedPurchases);
			getBasketFacade().save(this.basket);
		} catch (final DataNotStoredException e) {
			this.form.recordError(e.getLocalizedMessage());
			LOGGER.error(e);
			return;
		}
	}

	public Object onSuccess() {
		return this.viewPage;
	}

	Object onFailure() {
		return this.purchasesEditZone.getBody();
	}

	public Object onAddRow() {
		return new PurchaseDTO();
	}

	public void onRemoveRow(final PurchaseDTO purchase) {
		if (purchase.getId() != null) {
			getPurchaseFacade().delete(purchase);
		}
	}

	@OnEvent(value = "back")
	Object goBack() {
		return this.viewPage;
	}

	private String getPurchasesCosts() {
		double purchasesCost = 0d;
		if (this.purchases != null) {
			for (final PurchaseDTO purchase : this.purchases) {
				purchasesCost = purchasesCost + purchase.getCost();
			}
		}
		return String.valueOf(purchasesCost);
	}

	private IPurchaseFacade getPurchaseFacade() {
		return this.facadeFactory.getFacade(IPurchaseFacade.class);
	}

	private IBasketFacade getBasketFacade() {
		return this.facadeFactory.getFacade(IBasketFacade.class);
	}

}
